package com.qire.common.concurrent;

import com.qire.common.basic.ObjectUtil;

import java.util.concurrent.TimeUnit;

/**
 * 间隔循环
 * @param <T>
 */
public final class IntervalRunWrapper<T> extends RunWrapper<T, IntervalRunWrapper<T>> {

    private final long period;
    private final TimeUnit unit;

    private ExecuteWorker executeWorker;

    public IntervalRunWrapper(long period, TimeUnit unit) {
        super("IntervalRunWrapper");
        this.period = period;
        this.unit = unit;
    }

    /**
     * @return 创建一个工人
     */
    @Override
    protected ExecuteWorker buildWorker() {
        if(ObjectUtil.nonNull(executeWorker)) {
            executeWorker.stop();
            executeWorker = null;
        }
        executeWorker = new ExecuteWorker(worker);
        return executeWorker;
    }

    /**
     * 停止调度
     * @return IntervalRunWrapper<T>
     */
    public IntervalRunWrapper<T> stop() {
        if(ObjectUtil.nonNull(executeWorker)) {
            executeWorker.stop();
        }
        return this;
    }

    /**
     * 暂停调度
     * @return IntervalRunWrapper<T>
     */
    public IntervalRunWrapper<T> pause() {
        if(ObjectUtil.nonNull(executeWorker)) {
            executeWorker.pause();
        }
        return this;
    }

    /**
     * 运行调度
     * @return IntervalRunWrapper<T>
     */
    public IntervalRunWrapper<T> goPlay() {
        if(ObjectUtil.nonNull(executeWorker)) {
            executeWorker.goPlay();
        }
        return this;
    }

    /**
     * @return 暂停状态
     */
    public boolean isPause() {
        if(ObjectUtil.isNull(executeWorker)) {
            return true;
        }
        return executeWorker.isPause;
    }

    /**
     * @return 运行状态
     */
    public boolean isRunning() {
        if(ObjectUtil.isNull(executeWorker)) {
            return false;
        }
        return executeWorker.isRun;
    }

    /**
     * 执行工人
     */
    private class ExecuteWorker extends Worker<T> implements Runnable {

        /** 暂停锁 */
        private Object[] lockObj = new Object[0];

        /** 运行状态 */
        private volatile boolean isRun = true;

        /** 暂停状态 */
        private volatile boolean isPause = false;

        public ExecuteWorker(Worker<T> worker) {
            super(worker, Scheduler.Sync);
        }

        /** 停止调度 */
        public void stop() {
            isRun = false;
        }

        /** 暂停调度 */
        public void pause() {
            isPause = true;
        }

        /** 运行调度 */
        public void goPlay() {
            isPause = false;
            synchronized (lockObj) {
                lockObj.notify();
            }
        }

        @Override
        public void run() {
            while (isRun) {
                if(isPause) {
                    synchronized (lockObj) {
                        try {
                            lockObj.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
                accept(data);
                try {
                    unit.sleep(period);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    }


}
